package rbac

import (
	"context"
	"fmt"
	"gitee.com/bobo-rs/idea-space-framework/consts"
	"gitee.com/bobo-rs/idea-space-framework/enums"
	"gitee.com/bobo-rs/idea-space-framework/framework/dao"
	"gitee.com/bobo-rs/idea-space-framework/framework/model"
	"gitee.com/bobo-rs/idea-space-framework/pkg/exception"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
)

// SaveRoles 保存角色信息
func (r *sRbac) SaveRoles(ctx context.Context, role model.RolesDetailItem) error {
	// 保存数据
	return dao.Roles.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		res, err := dao.Roles.Ctx(ctx).
			OmitEmpty().
			Save(role.RolesItem)
		if err != nil {
			return exception.New(`保存角色失败`)
		}

		// 角色ID
		roleId, err := res.LastInsertId()
		if err != nil {
			return exception.New(`保存角色失败，ID为空`)
		}

		// 保存关联数据
		if len(role.PermId) > 0 {
			err = r.SavePermAssoc(ctx, uint(roleId), enums.PermAssocTypeRoles, role.PermId...)
		}
		return err
	})
}

// GetRolesList 获取角色列表
func (r *sRbac) GetRolesList(ctx context.Context, in model.RolesListInput) (out *model.RolesListOutput, err error) {
	out = &model.RolesListOutput{}
	// 获取角色列表
	err = r.RolesModel().ListAndTotal(ctx, model.CommonListAndTotalInput{
		CommonPaginationItem: in.CommonPaginationItem,
		Where:                r.RolesWhere(in),
		Sort:                 fmt.Sprintf(`%s %s, %s %s`, dao.Roles.Columns().Sort, consts.SortAsc, dao.Roles.Columns().Id, consts.SortDesc),
	}, &out.Rows, &out.Total)
	return
}

// GetAssocRolesList 获取关联角色列表
func (r *sRbac) GetAssocRolesList(ctx context.Context) (rows []model.RoleIdAndNameItem, err error) {
	rows = []model.RoleIdAndNameItem{}
	// 获取角色列表
	err = r.RolesModel().Scan(ctx, g.Map{
		dao.Roles.Columns().RoleStatus: enums.RoleStatusOk,
	}, &rows)
	if err != nil {
		return nil, exception.New(`暂无角色数据`)
	}
	return
}

// GetRolesDetail 获取角色详情
func (r *sRbac) GetRolesDetail(ctx context.Context, roleId uint) (detail *model.RolesDetailItem, err error) {
	detail = &model.RolesDetailItem{}

	// 获取角色信息
	err = r.RolesModel().Scan(ctx, g.Map{
		dao.Roles.Columns().Id: roleId,
	}, detail)
	if err != nil {
		return nil, exception.New(`暂无数据`)
	}

	// 获取权限ID
	detail.PermId, _ = r.GetPermissionsIdByRoleId(ctx, detail.Id)
	return
}

// RemoveRoles 删除角色信息
func (r *sRbac) RemoveRoles(ctx context.Context, roleId uint) error {
	if roleId == 0 {
		return exception.New(`缺少角色ID`)
	}
	// 删除角色
	return dao.Roles.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err := tx.Ctx(ctx).Delete(dao.Roles.Table(), g.Map{
			dao.Roles.Columns().Id: roleId,
		})
		if err != nil {
			return exception.New(`删除角色失败`)
		}
		// 移除绑定的部门
		if err = r.RemoveDepartmentRolesByRoleId(ctx, roleId); err != nil {
			return err
		}
		// 移除绑定权限
		return r.RemovePermAssocByAssocId(ctx, enums.PermAssocTypeRoles, roleId)
	})
}

// GetRolesNameListByRoleId 通过角色ID获取角色名列表
func (r *sRbac) GetRolesNameListByRoleId(ctx context.Context, roleId ...uint) (rows []model.RoleIdAndNameItem, err error) {
	if len(roleId) == 0 {
		return nil, exception.New(`缺少角色ID`)
	}
	rows = []model.RoleIdAndNameItem{}
	// 获取角色列表
	err = r.RolesModel().Scan(ctx, g.Map{
		dao.Roles.Columns().Id: roleId,
	}, &rows)
	if err != nil {
		return nil, exception.New(`暂无角色数据`)
	}
	return rows, nil
}
